package org.egedede.simulation.model.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.egedede.simulation.model.Model;
import org.egedede.simulation.model.ModelEvaluator;

/**
 * The Class MultiEvaluator.
 */
public class MultiEvaluator implements ModelEvaluator {
	
	/** The MA x_ mode. */
	public static final int MAX_MODE=0;
	
	/** The AD d_ mode. */
	public static final int ADD_MODE=1;
	
	
	/** The evaluators. */
	private Map<ModelEvaluator,Double> evaluators;
	
	/** The aggregation mode. */
	private int aggregationMode;
	
	
	
	/**
	 * Instantiates a new multi evaluator.
	 */
	public MultiEvaluator() {
		super();
		this.evaluators =  new HashMap<ModelEvaluator, Double>();
		this.aggregationMode = ADD_MODE;

	}

	/**
	 * Evaluate.
	 * 
	 * @param model the model
	 * 
	 * @return the evaluation
	 * 
	 * @see org.egedede.simulation.model.ModelEvaluator#evaluate(org.egedede.simulation.model.Model)
	 */
	@Override
	public double evaluate(final Model model) {
		double result = 0;
		Collection<Double> partialResults = new ArrayList<Double>(this.evaluators.size());
		for (Iterator<ModelEvaluator> iterator = this.evaluators.keySet().iterator(); iterator.hasNext();) {
			ModelEvaluator evaluator = iterator.next();
			double tmpResult = evaluator.evaluate(model)*this.evaluators.get(evaluator);
			partialResults.add(tmpResult);			
		}
		switch (this.aggregationMode) {
		case MultiEvaluator.ADD_MODE:
			for (Iterator<Double> iterator = partialResults.iterator(); iterator.hasNext();) {
				result+= iterator.next();
			}
			break;
		case MultiEvaluator.MAX_MODE:
			result = Double.MIN_VALUE;
			for (Iterator<Double> iterator = partialResults.iterator(); iterator.hasNext();) {
				result = Math.max(result,iterator.next());
			}
			break;
		default:
			break;
		}
		return result;
	}

	/**
	 * Gets the aggregation mode.
	 * 
	 * @return the aggregation mode
	 */
	public int getAggregationMode() {
		return this.aggregationMode;
	}
	
	/**
	 * Sets the aggregation mode.
	 * 
	 * @param aggregationMode the new aggregation mode
	 */
	public void setAggregationMode(int aggregationMode) {
		this.aggregationMode = aggregationMode;
	}

	/**
	 * Gets the evaluators.
	 * 
	 * @return the evaluators
	 */
	public Map<ModelEvaluator,Double> getEvaluators() {
		return this.evaluators;
	}
	
	/**
	 * Adds the evaluator.
	 * 
	 * @param evaluator the evaluator
	 * @param weight the weight
	 */
	public void addEvaluator(ModelEvaluator evaluator,double weight){
		this.evaluators.put(evaluator,weight);
	}

}
